/**
 * API测试工具
 * 
 * 用于测试数据库连接和API功能，验证环境配置是否正确
 * 
 * @module apiTester
 */

import fs from 'fs';
import path from 'path';
import http from 'http';
import https from 'https';
import { fileURLToPath } from 'url';
import { apiLogger } from './apiLogger.js';

// 获取当前文件目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

/**
 * 测试配置
 */
class ApiTester {
    /**
     * 创建API测试器
     * @param {Object} config - API配置
     */
    constructor(config) {
        this.config = config;
        this.baseUrl = config.AUTO_API_BASE_URL;
        this.projectId = config.PROJECT_ID;
        this.schemaName = config.SCHEMA_NAME;
        this.logger = apiLogger;
        this.results = {
            successful: 0,
            failed: 0,
            tests: []
        };
    }

    /**
     * 记录测试结果
     * @param {string} testName - 测试名称
     * @param {boolean} success - 是否成功
     * @param {Object} details - 测试细节
     */
    logResult(testName, success, details = {}) {
        const result = {
            name: testName,
            success,
            timestamp: new Date().toISOString(),
            ...details
        };

        this.results.tests.push(result);

        if (success) {
            this.results.successful++;
            console.log(`✅ 测试成功: ${testName}`);
        } else {
            this.results.failed++;
            console.error(`❌ 测试失败: ${testName}`, details.error || '');
        }

        return result;
    }

    /**
     * 发送HTTP请求
     * @param {string} url - 请求URL
     * @param {string} method - 请求方法
     * @param {Object} body - 请求体
     * @param {Object} headers - 请求头
     * @returns {Promise<Object>} 响应数据
     */
    async sendRequest(url, method = 'GET', body = null, headers = {}) {
        return new Promise((resolve, reject) => {
            const requestUrl = new URL(url);
            const options = {
                hostname: requestUrl.hostname,
                port: requestUrl.port || (requestUrl.protocol === 'https:' ? 443 : 80),
                path: requestUrl.pathname + requestUrl.search,
                method: method,
                headers: {
                    'Content-Type': 'application/json',
                    ...headers
                }
            };

            // 记录请求日志
            this.logger.logApiRequest(method, url, body, headers);

            const req = (requestUrl.protocol === 'https:' ? https : http).request(options, (res) => {
                let data = '';

                res.on('data', (chunk) => {
                    data += chunk;
                });

                res.on('end', () => {
                    let responseData;

                    try {
                        responseData = data ? JSON.parse(data) : {};
                    } catch (error) {
                        responseData = {
                            rawData: data,
                            parseError: error.message
                        };
                    }

                    // 记录响应日志
                    this.logger.logApiResponse(method, url, res.statusCode, responseData);

                    if (res.statusCode >= 200 && res.statusCode < 300) {
                        resolve({
                            statusCode: res.statusCode,
                            headers: res.headers,
                            data: responseData
                        });
                    } else {
                        reject({
                            statusCode: res.statusCode,
                            headers: res.headers,
                            data: responseData,
                            message: `HTTP错误: ${res.statusCode}`
                        });
                    }
                });
            });

            req.on('error', (error) => {
                this.logger.logApiError(method, url, error);
                reject({
                    message: `请求错误: ${error.message}`,
                    error
                });
            });

            if (body) {
                req.write(typeof body === 'string' ? body : JSON.stringify(body));
            }

            req.end();
        });
    }

    /**
     * 测试服务器连接
     * @returns {Promise<Object>} 测试结果
     */
    async testConnection() {
        try {
            const url = `${this.baseUrl}/ping`;
            const start = Date.now();
            const response = await this.sendRequest(url);
            const elapsed = Date.now() - start;

            return this.logResult('服务器连接测试', true, {
                url,
                statusCode: response.statusCode,
                responseTime: elapsed
            });
        } catch (error) {
            return this.logResult('服务器连接测试', false, {
                url: `${this.baseUrl}/ping`,
                error: error.message
            });
        }
    }

    /**
     * 测试API认证
     * @returns {Promise<Object>} 测试结果
     */
    async testAuthentication() {
        try {
            // 这里实现测试认证的逻辑
            // 具体取决于API的认证机制
            const url = `${this.baseUrl}/auth`;
            const body = {
                projectId: this.projectId
            };

            const response = await this.sendRequest(url, 'POST', body);

            // 判断认证是否成功
            const success = response.data && response.data.token;

            return this.logResult('API认证测试', success, {
                url,
                statusCode: response.statusCode,
                authSuccess: success
            });
        } catch (error) {
            return this.logResult('API认证测试', false, {
                error: error.message
            });
        }
    }

    /**
     * 测试获取数据库表信息
     * @returns {Promise<Object>} 测试结果
     */
    async testGetTables() {
        try {
            const url = `${this.baseUrl}/tables?projectId=${this.projectId}&schema=${this.schemaName}`;
            const response = await this.sendRequest(url);

            // 检查是否成功获取表列表
            const success = response.data && Array.isArray(response.data.tables);
            const tableCount = success ? response.data.tables.length : 0;

            return this.logResult('获取表列表测试', success, {
                url,
                tableCount,
                statusCode: response.statusCode
            });
        } catch (error) {
            return this.logResult('获取表列表测试', false, {
                error: error.message
            });
        }
    }

    /**
     * 测试获取表字段信息
     * @param {string} tableName - 表名
     * @returns {Promise<Object>} 测试结果
     */
    async testGetTableColumns(tableName) {
        try {
            const url = `${this.baseUrl}/columns?projectId=${this.projectId}&schema=${this.schemaName}&table=${tableName}`;
            const response = await this.sendRequest(url);

            // 检查是否成功获取列信息
            const success = response.data && Array.isArray(response.data.columns);
            const columnCount = success ? response.data.columns.length : 0;

            return this.logResult(`获取表${tableName}字段测试`, success, {
                url,
                tableName,
                columnCount,
                statusCode: response.statusCode
            });
        } catch (error) {
            return this.logResult(`获取表${tableName}字段测试`, false, {
                tableName,
                error: error.message
            });
        }
    }

    /**
     * 运行所有测试
     * @returns {Promise<Object>} 测试结果汇总
     */
    async runAllTests() {
        console.log('开始API测试...');

        // 清空之前的测试结果
        this.results = {
            successful: 0,
            failed: 0,
            tests: []
        };

        // 连接测试
        await this.testConnection();

        // 认证测试
        const authResult = await this.testAuthentication();

        // 如果认证成功，继续测试其他API
        if (authResult.success) {
            await this.testGetTables();

            // 测试一个示例表
            const tableName = 'user_table'; // 替换为实际表名
            await this.testGetTableColumns(tableName);
        }

        // 打印汇总结果
        console.log('\n测试完成!');
        console.log(`✅ 成功: ${this.results.successful}`);
        console.log(`❌ 失败: ${this.results.failed}`);

        return this.results;
    }

    /**
     * 保存测试结果到文件
     * @param {string} filePath - 文件路径
     * @returns {boolean} 是否保存成功
     */
    saveResults(filePath) {
        try {
            const dir = path.dirname(filePath);
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
            }

            fs.writeFileSync(
                filePath,
                JSON.stringify(this.results, null, 2),
                'utf8'
            );

            console.log(`测试结果已保存到: ${filePath}`);
            return true;
        } catch (error) {
            console.error('保存测试结果失败:', error);
            return false;
        }
    }
}

// 当脚本直接运行时执行测试
if (import.meta.url === `file://${process.argv[1]}`) {
    const configPath = path.join(__dirname, 'env.config');

    // 简单的配置加载
    const loadConfig = () => {
        try {
            const config = {};
            const content = fs.readFileSync(configPath, 'utf8');

            content.split('\n').forEach(line => {
                if (line.trim().startsWith('#') || !line.trim()) return;

                const match = line.match(/^([A-Z0-9_]+)="([^"]*)"/);
                if (match) {
                    const [, key, value] = match;
                    config[key] = value;
                }
            });

            return config;
        } catch (error) {
            console.error('加载配置文件失败:', error);
            return {
                AUTO_API_BASE_URL: 'http://localhost:3000',
                PROJECT_ID: 'demo',
                SCHEMA_NAME: 'public'
            };
        }
    };

    const config = loadConfig();
    const tester = new ApiTester(config);

    tester.runAllTests().then(results => {
        const outputPath = path.join(__dirname, '../logs/api-test-results.json');
        tester.saveResults(outputPath);

        // 根据测试结果设置退出码
        process.exit(results.failed > 0 ? 1 : 0);
    });
}

export default ApiTester; 